package com.dly.hope.service.impl;

import com.dly.hope.annotation.Clear;
import com.dly.hope.annotation.SysLog;
import com.dly.hope.constant.ExceptionConstant;
import com.dly.hope.dao.ShowContentDao;
import com.dly.hope.model.ro.CommentRo;
import com.dly.hope.model.ro.GetUserShowRo;
import com.dly.hope.model.ro.ReleaseRo;
import com.dly.hope.model.vo.CommentVo;
import com.dly.hope.model.vo.PraiseUserVo;
import com.dly.hope.model.vo.ShowVo;
import com.dly.hope.model.vo.SimpleUserVo;
import com.dly.hope.modle.*;
import com.dly.hope.repository.*;
import com.dly.hope.service.ShowService;
import com.dly.hope.type.MessageType;
import com.dly.hope.utils.ExceptionPropertiesUtil;
import com.dly.hope.pageUtils.Page;
import com.dly.hope.pageUtils.PageRo;
import com.dly.hope.webSocket.WebSocketServer;
import com.dly.hope.webSocket.dto.MessageDto;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ShowServiceImpl implements ShowService {

    @Resource
    private ShowContentRepository showContentRepository;

    @Resource
    private ShowImageRepository showImageRepository;

    @Resource
    private ShowContentDao showContentDao;

    @Resource
    private UserAccountRepository userAccountRepository;

    @Resource
    private ShowPraiseRepository showPraiseRepository;

    @Resource
    private FriendRepository friendRepository;

    @Resource
    private ShowCommentRepository showCommentRepository;

    @Value(value = "${file.load.imagePath}")
    private String imagePath;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Clear(clazz = ShowServiceImpl.class,methodName = {"getAllShow","getUserShow"})
    public void release(String userId, ReleaseRo releaseRo) {
        ShowContent showContent = new ShowContent();
        showContent.setText(releaseRo.getText());
        showContentRepository.saveAndFlush(showContent);
        releaseRo.getImages().forEach(imageId -> {
            ShowImage showImage = new ShowImage();
            showImage.setShowId(showContent.getId());
            showImage.setImageId(imageId);
            showImageRepository.save(showImage);
        });

        //通知好友
        List<String> friendIds = friendRepository.findAllByUserIdAndIsAgreeAndDataStatus(userId, 1, 1).stream().map(Friend::getFriendId).collect(Collectors.toList());
        userAccountRepository.findByIdAndDataStatus(userId, 1)
                .filter(userAccount -> userAccount.getIntoShow() == 0)
                .ifPresent(userAccount -> {
                    userAccountRepository.findAllByIdInAndDataStatus(friendIds, 1).forEach(userAccount1 -> {
                        MessageDto messageDto = new MessageDto();
                        messageDto.setType(MessageType.NOTICE);
                        WebSocketServer.invite(messageDto, userAccount, userAccount1);
                    });
                });
    }

    @Override
    @SysLog
    public Page<ShowVo> getAllShow(String userId, PageRo pageRo) {
        List<String> friendIds = friendRepository.findAllByUserIdAndIsAgreeAndDataStatus(userId, 1, 1)
                .stream().map(Friend::getFriendId).collect(Collectors.toList());

        //去掉不展示的
        List<String> friendIdo = userAccountRepository.findAllByIdInAndDataStatus(friendIds, 1)
                .stream().filter(userAccount -> userAccount.getIntoShow() == 0 || userAccount.getId().equals(userId))
                .map(UserAccount::getId)
                .collect(Collectors.toList());
        friendIdo.add(userId);

        Page<ShowVo> page = showContentDao.getAllPage(pageRo, friendIdo);
        List<ShowVo> content = page.getContent();
        List<String> userIds = content.stream().map(ShowVo::getUserId).collect(Collectors.toList());
        List<String> showIds = content.stream().map(ShowVo::getId).collect(Collectors.toList());
        //发帖用户
        Map<String, UserAccount> userAccountMap = userAccountRepository.findAllByIdInAndDataStatus(userIds, 1)
                .stream()
                .collect(Collectors.toMap(UserAccount::getId, userAccount -> userAccount, (old, now) -> now));
        //图片
        Map<String, List<ShowImage>> showAndImageMap = showImageRepository.findAllByShowIdInAndDataStatus(showIds, 1)
                .stream()
                .collect(Collectors.groupingBy(ShowImage::getShowId));
        //点赞
        List<ShowPraise> allByShowIdInAndDataStatus = showPraiseRepository.findAllByShowIdInAndDataStatus(showIds, 1);
        Map<String, List<ShowPraise>> showAndPraiseMap = allByShowIdInAndDataStatus
                .stream()
                .collect(Collectors.groupingBy(ShowPraise::getShowId));
        //点赞用户
        List<String> praiseUserAllIds = allByShowIdInAndDataStatus.stream().map(ShowPraise::getUserId).distinct().collect(Collectors.toList());
        Map<String, UserAccount> praiseUserMap = userAccountRepository.findAllByIdInAndDataStatus(praiseUserAllIds, 1)
                .stream()
                .collect(Collectors.toMap(UserAccount::getId, userAccount -> userAccount, (old, now) -> now));

        //评论
        List<ShowComment> allShowComment = showCommentRepository.findAllByShowIdInAndDataStatus(showIds, 1);
        List<String> replyIds = allShowComment.stream().map(ShowComment::getReplyId).collect(Collectors.toList());
        List<String> sendIds = allShowComment.stream().map(ShowComment::getCreateUser).collect(Collectors.toList());
        replyIds.addAll(sendIds);

        Map<String, UserAccount> commentUserMap = userAccountRepository.findAllByIdInAndDataStatus(replyIds, 1)
                .stream()
                .collect(Collectors.toMap(UserAccount::getId, userAccount -> userAccount, (old, now) -> now));
        Map<String, List<ShowComment>> showIdAndShowComment = allShowComment
                .stream()
                .collect(Collectors.groupingBy(ShowComment::getShowId));

        content.forEach(showVo -> {
            UserAccount userAccount = userAccountMap.get(showVo.getUserId());
            showVo.setName(userAccount.getAccountName());
            showVo.setAvatar(userAccount.getAvatar());
            List<ShowImage> showImages = showAndImageMap.get(showVo.getId());
            List<String> images = null;
            if(showImages!=null){
                images = showImages.stream().map(showImage -> imagePath + showImage.getImageId()).collect(Collectors.toList());
            }
            showVo.setImages(images);
            showVo.setShowPraise(false);

            List<ShowPraise> showPraises = showAndPraiseMap.get(showVo.getId());
            if (showPraises != null) {
                List<String> praiseUserIds = showPraises.stream().sorted((a1, a2) -> {
                    //前一个的时间
                    Date date1 = a1.getCreateDate();
                    Date date2 = a2.getCreateDate();

                    if (date2.before(date1)) {
                        return -1;
                    }
                    return 1;
                }).map(ShowPraise::getUserId).collect(Collectors.toList());
                showVo.setShowPraise(praiseUserIds.contains(userId));
                ArrayList<PraiseUserVo> praiseUserVos = new ArrayList<>();
                praiseUserIds.forEach(id -> {
                    UserAccount userAccount1 = praiseUserMap.get(id);
                    PraiseUserVo praiseUserVo = new PraiseUserVo();
                    praiseUserVo.setName(userAccount1.getAccountName());
                    praiseUserVo.setUserId(userAccount1.getId());
                    praiseUserVos.add(praiseUserVo);
                });
                showVo.setPraiseUserList(praiseUserVos);
            }

            //评论
            List<CommentVo> commentVos = new ArrayList<>();
            //当前下面的所有评论
            List<ShowComment> showComments = showIdAndShowComment.get(showVo.getId());
            if (showComments != null) {
                //所有的父级评论
                List<ShowComment> parentComment = showComments.stream().filter(showComment -> showComment.getParentId().isEmpty()).collect(Collectors.toList());
                //对所有的父级评论进行分组
                Map<String, List<ShowComment>> childComment = showComments.stream().collect(Collectors.groupingBy(ShowComment::getParentId));
                parentComment.forEach(showComment -> {
                    CommentVo commentVo = new CommentVo();
                    commentVo.setId(showComment.getId());
                    commentVo.setContent(showComment.getContent());
                    commentVo.setCreateDate(showComment.getCreateDate());
                    //评论用户
                    UserAccount sendUser = commentUserMap.get(showComment.getCreateUser());
                    commentVo.setSendUser(new SimpleUserVo(sendUser));
                    //遍历子集评论
                    List<CommentVo> childComments = new ArrayList<>();
                    List<ShowComment> showComments1 = childComment.get(showComment.getId());
                    if (showComments1 != null) {
                        showComments1.forEach(showComment1 -> {
                            CommentVo childcommentVo = new CommentVo();
                            childcommentVo.setId(showComment1.getId());
                            childcommentVo.setContent(showComment1.getContent());
                            childcommentVo.setCreateDate(showComment1.getCreateDate());
                            //评论用户
                            UserAccount childSendUser = commentUserMap.get(showComment1.getCreateUser());
                            childcommentVo.setSendUser(new SimpleUserVo(childSendUser));

                            UserAccount childReplyUser = commentUserMap.get(showComment1.getReplyId());
                            childcommentVo.setReplyUser(new SimpleUserVo(childReplyUser));
                            childComments.add(childcommentVo);
                        });
                    }
                    //排序
                    childComments.sort((a1, a2) -> {
                        //前一个的时间
                        Date date1 = a1.getCreateDate();
                        Date date2 = a2.getCreateDate();

                        if (date2.before(date1)) {
                            return 1;
                        }
                        return -1;
                    });
                    commentVo.setChildComment(childComments);
                    commentVos.add(commentVo);
                });
            }

            commentVos.sort((a1, a2) -> {
                //前一个的时间
                Date date1 = a1.getCreateDate();
                Date date2 = a2.getCreateDate();

                if (date2.before(date1)) {
                    return 1;
                }
                return -1;
            });
            showVo.setCommentVos(commentVos);
        });
        return page;
    }

    @Override
    @SysLog
    public Page<ShowVo> getUserShow(String userId, GetUserShowRo getUserShowRo) {
        Page<ShowVo> page = showContentDao.getUserPage(getUserShowRo);
        List<ShowVo> content = page.getContent();
        UserAccount userAccount = userAccountRepository.findByIdAndDataStatus(getUserShowRo.getUserId(), 1).orElseThrow(() -> ExceptionPropertiesUtil.getException(ExceptionConstant.USER_ACCOUNT_NULL));

        if (!userAccount.getId().equals(userId) && userAccount.getIntoShow().equals(1)) {
            throw ExceptionPropertiesUtil.getException(ExceptionConstant.NO_PERMISSION);
        }

        List<String> showIds = content.stream().map(ShowVo::getId).collect(Collectors.toList());
        Map<String, List<ShowImage>> showAndImageMap = showImageRepository.findAllByShowIdInAndDataStatus(showIds, 1)
                .stream()
                .collect(Collectors.groupingBy(ShowImage::getShowId));

        //点赞
        List<ShowPraise> allByShowIdInAndDataStatus = showPraiseRepository.findAllByShowIdInAndDataStatus(showIds, 1);
        Map<String, List<ShowPraise>> showAndPraiseMap = allByShowIdInAndDataStatus
                .stream()
                .collect(Collectors.groupingBy(ShowPraise::getShowId));
        //点赞用户
        List<String> praiseUserAllIds = allByShowIdInAndDataStatus.stream().map(ShowPraise::getUserId).distinct().collect(Collectors.toList());
        Map<String, UserAccount> praiseUserMap = userAccountRepository.findAllByIdInAndDataStatus(praiseUserAllIds, 1)
                .stream()
                .collect(Collectors.toMap(UserAccount::getId, userAccount1 -> userAccount1, (old, now) -> now));

        //评论
        List<ShowComment> allShowComment = showCommentRepository.findAllByShowIdInAndDataStatus(showIds, 1);
        List<String> replyIds = allShowComment.stream().map(ShowComment::getReplyId).collect(Collectors.toList());
        List<String> sendIds = allShowComment.stream().map(ShowComment::getCreateUser).collect(Collectors.toList());
        replyIds.addAll(sendIds);

        Map<String, UserAccount> commentUserMap = userAccountRepository.findAllByIdInAndDataStatus(replyIds, 1)
                .stream()
                .collect(Collectors.toMap(UserAccount::getId, userAccount1 -> userAccount1, (old, now) -> now));
        Map<String, List<ShowComment>> showIdAndShowComment = allShowComment
                .stream()
                .collect(Collectors.groupingBy(ShowComment::getShowId));

        content.forEach(showVo -> {
            showVo.setName(userAccount.getAccountName());
            showVo.setAvatar(userAccount.getAvatar());
            List<ShowImage> showImages = showAndImageMap.get(showVo.getId());
            List<String> images = null;
            if(showImages!=null){
               images = showImages.stream().map(showImage -> imagePath + showImage.getImageId()).collect(Collectors.toList());
            }
            showVo.setImages(images);
            showVo.setShowPraise(false);

            List<ShowPraise> showPraises = showAndPraiseMap.get(showVo.getId());
            if (showPraises != null) {
                List<String> praiseUserIds = showPraises.stream().sorted((a1, a2) -> {
                    //前一个的时间
                    Date date1 = a1.getCreateDate();
                    Date date2 = a2.getCreateDate();

                    if (date2.before(date1)) {
                        return -1;
                    }
                    return 1;
                }).map(ShowPraise::getUserId).collect(Collectors.toList());
                showVo.setShowPraise(praiseUserIds.contains(userId));
                ArrayList<PraiseUserVo> praiseUserVos = new ArrayList<>();
                praiseUserIds.forEach(id -> {
                    UserAccount userAccount1 = praiseUserMap.get(id);
                    PraiseUserVo praiseUserVo = new PraiseUserVo();
                    praiseUserVo.setName(userAccount1.getAccountName());
                    praiseUserVo.setUserId(userAccount1.getId());
                    praiseUserVos.add(praiseUserVo);
                });
                showVo.setPraiseUserList(praiseUserVos);
            }

            //评论
            List<CommentVo> commentVos = new ArrayList<>();
            //当前下面的所有评论
            List<ShowComment> showComments = showIdAndShowComment.get(showVo.getId());
            if (showComments != null) {
                //所有的父级评论
                List<ShowComment> parentComment = showComments.stream().filter(showComment -> showComment.getParentId().isEmpty()).collect(Collectors.toList());
                //对所有的父级评论进行分组
                Map<String, List<ShowComment>> childComment = showComments.stream().collect(Collectors.groupingBy(ShowComment::getParentId));
                parentComment.forEach(showComment -> {
                    CommentVo commentVo = new CommentVo();
                    commentVo.setId(showComment.getId());
                    commentVo.setContent(showComment.getContent());
                    commentVo.setCreateDate(showComment.getCreateDate());
                    //评论用户
                    UserAccount sendUser = commentUserMap.get(showComment.getCreateUser());
                    commentVo.setSendUser(new SimpleUserVo(sendUser));
                    //遍历子集评论
                    List<CommentVo> childComments = new ArrayList<>();
                    List<ShowComment> showComments1 = childComment.get(showComment.getId());
                    if (showComments1 != null) {
                        showComments1.forEach(showComment1 -> {
                            CommentVo childcommentVo = new CommentVo();
                            childcommentVo.setId(showComment1.getId());
                            childcommentVo.setContent(showComment1.getContent());
                            childcommentVo.setCreateDate(showComment1.getCreateDate());
                            //评论用户
                            UserAccount childSendUser = commentUserMap.get(showComment1.getCreateUser());
                            childcommentVo.setSendUser(new SimpleUserVo(childSendUser));

                            UserAccount childReplyUser = commentUserMap.get(showComment1.getReplyId());
                            childcommentVo.setReplyUser(new SimpleUserVo(childReplyUser));
                            childComments.add(childcommentVo);
                        });
                    }
                    //排序
                    childComments.sort((a1, a2) -> {
                        //前一个的时间
                        Date date1 = a1.getCreateDate();
                        Date date2 = a2.getCreateDate();

                        if (date2.before(date1)) {
                            return 1;
                        }
                        return -1;
                    });
                    commentVo.setChildComment(childComments);
                    commentVos.add(commentVo);
                });
            }

            commentVos.sort((a1, a2) -> {
                //前一个的时间
                Date date1 = a1.getCreateDate();
                Date date2 = a2.getCreateDate();

                if (date2.before(date1)) {
                    return 1;
                }
                return -1;
            });
            showVo.setCommentVos(commentVos);
        });
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Clear(clazz = ShowServiceImpl.class,methodName = {"getAllShow","getUserShow"})
    public void praise(String userId, String showId) {
        Optional<ShowPraise> showPraiseOptional = showPraiseRepository.findTopByUserIdAndShowId(userId, showId);
        if (showPraiseOptional.isEmpty()) {
            ShowPraise showPraise = new ShowPraise();
            showPraise.setShowId(showId);
            showPraise.setUserId(userId);
            showPraiseRepository.save(showPraise);
        } else {
            showPraiseOptional.ifPresent(showPraise -> {
                if (showPraise.getDataStatus().equals(1)) {
                    showPraise.setDataStatus(0);
                } else {
                    showPraise.setDataStatus(1);
                }
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Clear(clazz = ShowServiceImpl.class,methodName = {"getAllShow","getUserShow"})
    public void comment(CommentRo commentRo) {
        ShowComment showComment = new ShowComment();
        showComment.setParentId(commentRo.getParentId());
        showComment.setContent(commentRo.getComment());
        showComment.setReplyId(commentRo.getReplyId());
        showComment.setShowId(commentRo.getShowId());
        showCommentRepository.save(showComment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Clear(clazz = ShowServiceImpl.class,methodName = {"getAllShow","getUserShow"})
    public void deleteShow(String showId, String userId) {
        showContentRepository.findTopByIdAndDataStatus(showId, 1)
                .filter(showContent -> showContent.getCreateUser().equals(userId))
                .map(showContent -> {
                    showContent.setDataStatus(0);
                    return true;
                }).orElseThrow(() -> ExceptionPropertiesUtil.getException(ExceptionConstant.NO_PERMISSION));
    }

}
